
using System;
using System.Collections.Generic;
using System.Reflection;

namespace QQZiFramework
{
    public class EntityLoaderInfo
    {
        Type type;
        List<CustomerProperty> m_customerPropertys, m_foreignCusPros;
        CustomerProperty m_primaryCusPro, m_markDeleteKey;
        DBTableAttribute m_tableAttr;
        System.Collections.Hashtable dic_customerPropertys = new System.Collections.Hashtable();

        public PropertyInfo OverrideFieldInfo,OverrideTableInfo;//实体里面有重写字段名（数据库）和重新表名的


        public EntityLoaderInfo(Type t)
        {
            type = t;
            m_customerPropertys = GetTypeCustomerPropertys();
            m_tableAttr = DBContext.GET_TABLE_ATTR_STATIC(t);
            m_primaryCusPro = GetUsaAttrOnce(DBFieldUsage.PrimaryKey);
            m_markDeleteKey = GetUsaAttrOnce(DBFieldUsage.MarkDelete);
            OverrideFieldInfo= type.GetProperty("__OVERRIDE_FIELD_NAME__");
            OverrideTableInfo= type.GetProperty("__OVERRIDE_TABLE_NAME__");
            if (m_markDeleteKey != null && !IDBEntity.IsNullableType(m_markDeleteKey.Info.PropertyType))
            {
                throw new Exception("标记删除列" + m_markDeleteKey.Info.Name + "必需是可空类型");
            }
            m_foreignCusPros = CustomerPropertys.FindAll(x => x.Attr != null && x.Attr.Usage == DBFieldUsage.ForeignKey);
            foreach (CustomerProperty cp in m_customerPropertys)
            {
                if (cp.Attr != null && cp.Attr.Usage == DBFieldUsage.NoField) continue;
                dic_customerPropertys.Add(cp.Info.Name, cp);
            }
        }
        /// <summary>
        /// 获取有DBFieldAttribute自定义属性集合
        /// </summary>
        public List<CustomerProperty> CustomerPropertys { get { return m_customerPropertys; } }


        public Type EntityType { get { return type; } }

        /// <summary>
        /// 主键自定义属性
        /// </summary>
        public CustomerProperty PrimaryCusPro
        {
            get
            {
                if (m_primaryCusPro == null) throw new ClientException("实体" + type.Name + "没有定义主键");
                return m_primaryCusPro;
            }
        }

        /// <summary>
        /// 标记删除
        /// </summary>
        public CustomerProperty MarkDeleteCusPro
        {
            get
            {
                return m_markDeleteKey;
            }
        }

        /// <summary>
        /// 外键自定义属性集合
        /// </summary>
        public List<CustomerProperty> ForeignCusPros { get { return m_foreignCusPros; } }


        /// <summary>
        /// 表名
        /// </summary>

        public DBTableAttribute TableAttr
        {
            get
            {
                return m_tableAttr;
            }
        }


        /// <summary>
        /// 获取实体类型的自定义属性集合
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        List<CustomerProperty> GetTypeCustomerPropertys()
        {
            List<CustomerProperty> lst = new List<CustomerProperty>();
            foreach (PropertyInfo proInfo in type.GetProperties())
            {
                object[] fieldAttrs = proInfo.GetCustomAttributes(typeof(DBFieldAttribute), true);
                if (fieldAttrs.Length > 0)
                {
                    DBFieldAttribute attr = fieldAttrs[0] as DBFieldAttribute;
                    //if (string.IsNullOrEmpty(attr.FieldName)) attr.FieldName = proInfo.Name;
                    lst.Add(new CustomerProperty() { Info = proInfo, Attr = attr });
                }
                else lst.Add(new CustomerProperty() { Info = proInfo });
            }
            if (lst.Count == 0) throw new ClientException(type.Name + "没有定义任何属性");
            return lst;
        }

        /// <summary>
        /// 获取parent字段的数据库列名,客户端树加载用
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public CustomerProperty GetParentCustomerProperty()
        {
            if (ForeignCusPros != null && ForeignCusPros.Count > 0)
            {
                return ForeignCusPros[0];
            }
            throw new ClientException("类型" + this.type.Name + "没有指定parent外键");
        }

        /// <summary>
        /// 获取实体中第一个定义了指定的Usage的字段属性
        /// </summary>
        public CustomerProperty GetUsaAttrOnce(DBFieldUsage usa)
        {
            foreach (CustomerProperty proInfo in CustomerPropertys)
            {

                if (proInfo.Attr != null && proInfo.Attr.Usage == usa)
                {

                    return proInfo;
                }

            }
            return null;
        }


        /// <summary>
        /// 获取指定Usage的属性和自定义属性
        /// </summary>
        public List<CustomerProperty> GetUsaAttr(DBFieldUsage usa)
        {
            return CustomerPropertys.FindAll(x => x.Attr != null && x.Attr.Usage == usa);
        }

        static Dictionary<Type, EntityLoaderInfo> typeCustomerPropertyDic = new Dictionary<Type, EntityLoaderInfo>();



        public static EntityLoaderInfo GetEntityLoaderInfo(Type type)
        {
            //解析实体
            EntityLoaderInfo loaderInfo;
            if (!typeCustomerPropertyDic.TryGetValue(type, out loaderInfo))
            {
                lock (typeCustomerPropertyDic)
                {
                    loaderInfo = new EntityLoaderInfo(type);

                }
            }
            return loaderInfo;
        }



        /// <summary>
        /// 获取类型的某个属性及自定义属性
        /// </summary>
        /// <param name="t">类型</param>
        /// <param name="name">属性名</param>
        /// <returns></returns>
        public CustomerProperty GetCustomerProperty(string name)
        {
            // foreach (CustomerProperty per in ForeignCusPros)
            // {
            //     if (per.Info.Name == name) return per;
            // }
            // return null;
            return dic_customerPropertys[name] as CustomerProperty;
        }


        /// <summary>
        /// 通过数据库字段获取属性
        /// </summary>
        /// <param name="dbFieldName"></param>
        /// <returns></returns>
        public CustomerProperty GetPropertyByDBName(string dbFieldName)
        {
            if (dbFieldName == null) throw new ClientException("GetPropertyByDBName dbfieldName is not allow null");
            List<CustomerProperty> lst = CustomerPropertys.FindAll(x => x.GetDBFieldName(null) == dbFieldName);
            if (lst.Count > 0) return lst[0];
            else throw new ClientException(type + "不包含数据字段" + dbFieldName + "对应的属性定义!");
        }





    }

}